package com.example.listener;

import cn.hutool.core.util.ReflectUtil;
import com.example.annotation.TestAfter;
import com.example.annotation.TestBefore;
import com.example.annotation.TestCache;
import com.example.annotation.TestSendSms;
import com.example.handler.TestHandler;
import com.example.utils.VelocityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;

@Component
@Aspect
public class HandlerAopAspect implements ApplicationContextAware {

    Logger logger = LoggerFactory.getLogger(getClass());

    private ApplicationContext applicationContext;

    @Pointcut("execution(public * com.example.service.*.*(..))")
    public void doOperation() {

    }

    @Around(value = "doOperation()")
    public Object arroud(ProceedingJoinPoint joinPoint) {
        Object object = null;
        try {
            if (joinPoint instanceof MethodInvocationProceedingJoinPoint) {
                Method method = ReflectUtil.getMethodByName(joinPoint.getSignature().getDeclaringType(), joinPoint.getSignature().getName());
                if (method.isAnnotationPresent(TestBefore.class)) {
                    TestBefore testBefore = method.getAnnotation(TestBefore.class);
                    if (!StringUtils.isEmpty(testBefore.value())) {
                        Object bean = this.applicationContext.getBean(testBefore.value());
                        if (bean instanceof TestHandler) {
                            ((TestHandler) bean).exec();
                        }
                    }
                }
                if (method.isAnnotationPresent(TestCache.class)) {
                    TestCache testCache = method.getAnnotation(TestCache.class);
                    logger.info("testCache解析参数后的表达式：" + VelocityUtils.process(joinPoint, testCache.value()));
                }
            }
            object = joinPoint.proceed();
            if (joinPoint instanceof MethodInvocationProceedingJoinPoint) {
                Method method = ReflectUtil.getMethodByName(joinPoint.getSignature().getDeclaringType(), joinPoint.getSignature().getName());
                if (method.isAnnotationPresent(TestAfter.class)) {
                    TestAfter testAfter = method.getAnnotation(TestAfter.class);
                    if (!StringUtils.isEmpty(testAfter.value())) {
                        Object bean = this.applicationContext.getBean(testAfter.value());
                        if (bean instanceof TestHandler) {
                            ((TestHandler) bean).exec();
                        }
                    }
                }
                if (method.isAnnotationPresent(TestSendSms.class)) {
                    TestSendSms testSendSms = method.getAnnotation(TestSendSms.class);
                    if (!StringUtils.isEmpty(testSendSms.value())) {
                        logger.info("testSendSms解析参数后的表达式：" + VelocityUtils.process(joinPoint, testSendSms.value()));
                    }
                }
            }
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return object;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}